﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Microsoft.Office.OneNote
{
    [Serializable]
    public enum OneNotePageOrientation
    {
        Portrait = 0,
        Landscape = 1
    }

    [OneNoteXmlElement("PageSize")]
    public sealed class OneNotePageSize : OneNoteObject, IEquatable<OneNotePageSize>
    {
        private const string AutomaticString = "Automatic";
        private const string ToStringFormat = "Orientation={0}, Dimensions={{{1}}}, Margins={2}";

        internal static readonly OneNoteProperty AutomaticProperty = OneNoteProperty.Register(
            "Automatic", typeof(AutomaticPlaceholder), typeof(OneNotePageSize), null);

        internal static readonly OneNoteProperty OrientationProperty = OneNoteProperty.Register(
            "Orientation", typeof(PageOrientation), typeof(OneNotePageSize), null);

        internal static readonly OneNoteProperty DimensionsProperty = OneNoteProperty.Register(
            "Dimensions", typeof(OneNotePageDimensions), typeof(OneNotePageSize), null);

        internal static readonly OneNoteProperty MarginsProperty = OneNoteProperty.Register(
            "Margins", typeof(OneNotePageMargins), typeof(OneNotePageSize), null);
        
        public bool IsAutomatic
        {
            get { return GetValue(AutomaticProperty) != null; }
            set
            {
                if (value)
                {
                    SetValue(AutomaticProperty, new AutomaticPlaceholder());
                    SetValue(DimensionsProperty, null);
                    SetValue(MarginsProperty, null);
                }
            }
        }

        public OneNotePageOrientation Orientation
        {
            get
            {
                PageOrientation po = GetValue<PageOrientation>(OrientationProperty);

                if (po == null || !po.Landscape)
                {
                    return OneNotePageOrientation.Portrait;    
                }

                return OneNotePageOrientation.Landscape;
            }
            set
            {
                if (value == Orientation)
                {
                    return;
                }

                if (value == OneNotePageOrientation.Landscape)
                {
                    PageOrientation po = new PageOrientation();
                    po.Landscape = true;

                    SetValue(OrientationProperty, po);
                }
                else
                {
                    SetValue(OrientationProperty, null);
                }

                SetValue(AutomaticProperty, null);
            }
        }

        public OneNotePageDimensions Dimensions
        {
            get { return GetValue<OneNotePageDimensions>(DimensionsProperty); }
            set { SetValue(DimensionsProperty, value); }
        }

        public OneNotePageMargins Margins
        {
            get { return GetValue<OneNotePageMargins>(MarginsProperty); }
            set { SetValue(MarginsProperty, value); }
        }

        public override int GetHashCode()
        {
            if (IsAutomatic)
            {
                return 0;
            }

            return Orientation.GetHashCode() ^ 
                   Dimensions.GetHashCode() ^
                   Margins.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            return this.EqualsHelper(obj);
        }

        public bool Equals(OneNotePageSize other)
        {
            if (ReferenceEquals(other, null))
            {
                return false;
            }

            if (other.IsAutomatic)
            {
                return IsAutomatic;
            }

            return other.Orientation.Equals(Orientation) &&
                   other.Dimensions.Equals(Dimensions) &&
                   other.Margins.Equals(Margins);
        }

        public override string ToString()
        {
            if (IsAutomatic)
            {
                return AutomaticString;
            }

            return base.ToString();
        }

        public static bool operator ==(OneNotePageSize left, OneNotePageSize right)
        {
            if (ReferenceEquals(left, null))
            {
                return ReferenceEquals(right, null);
            }

            return left.Equals(right);
        }

        public static bool operator !=(OneNotePageSize left, OneNotePageSize right)
        {
            if (ReferenceEquals(left, null))
            {
                return !ReferenceEquals(right, null);
            }

            return !left.Equals(right);
        }

        public static OneNotePageSize Automatic
        {
            get
            {
                OneNotePageSize size = new OneNotePageSize();
                size.SetValue(AutomaticProperty, new AutomaticPlaceholder());

                return size;
            }
        }

        [OneNoteXmlElement("Orientation")]
        private sealed class PageOrientation : OneNoteObject
        {
            internal static readonly OneNoteProperty LandscapeProperty = OneNoteProperty.Register(
                "landscape", typeof(Boolean), typeof(PageOrientation), false);

            public Boolean Landscape
            {
                get { return GetValue<Boolean>(LandscapeProperty); }
                set { SetValue(LandscapeProperty, value);}
            }
        }
    }
}
